/*
 * Copyright © 2004-2014 chenYuan. All rights reserved.
 * @Website:wwww.jspx.net
 * @Mail:39793751@qq.com
 * @author: chenYuan , 陈原
 * @License: Jspx.net Framework Code is open source (LGPL)，Jspx.net Framework 使用LGPL 开源授权协议发布。
 * @jvm:jdk1.6+  x86/amd64
 *
 */
package com.jspx.txweb.action;

import com.jspx.boot.EnvFactory;
import com.jspx.boot.environment.Environment;
import com.jspx.boot.sign.LanguageRes;
import com.jspx.boot.sign.LoginField;
import com.jspx.boot.sign.UserType;
import com.jspx.boot.sign.YesNoType;
import com.jspx.json.JSONArray;
import com.jspx.json.JSONObject;
import com.jspx.txweb.IUserSession;
import com.jspx.txweb.annotation.HttpMethod;
import com.jspx.txweb.annotation.Safety;
import com.jspx.txweb.dao.PermissionDAO;
import com.jspx.txweb.env.TXWeb;
import com.jspx.txweb.env.TXWebIoc;
import com.jspx.txweb.util.RequestUtil;
import com.jspx.txweb.view.AuthenticationView;
import com.jspx.utils.*;
import com.jspx.txweb.annotation.Validate;
import com.jspx.txweb.annotation.Operate;
import com.jspx.sioc.annotation.Ref;
import com.jspx.txweb.online.OnlineManager;

import java.util.Map;

/**
 * Created by IntelliJ IDEA.
 * User:chenYuan (mail:39793751@qq.com)
 * Date: 2004-5-18
 * Time: 17:25:06
 * 说明本程序可以实现OOS方式的单点登录，跨子域名,但并不能够 完整的跨顶级域名,
 * 如果要求跨顶级域名需要接口
 * 采用分发seesionID的方式
 */
@HttpMethod(caption = "会员")
public class BaseUserAction extends AuthenticationView {

    //模式 0:提交方式  1:ajax 方式,返回json;
    private int mode = 0;

    //保存时间
    private int cookieDate = DateUtil.HOUR * 24;
    //登录后要跳转的页面

    //验证码
    private String validate;

    //如果为true ,那么管理员登陆必须是已经前台登陆的用户
    private boolean safeManageLogin = false;

    //登录后要跳转的页面
    private String[] allowHost;

    private String redirectUrl = StringUtil.empty;

    public String getRedirectUrl() {
        if (!StringUtil.isNULL(redirectUrl) && !redirectUrl.endsWith(request.getRequestURI()) && !redirectUrl.endsWith(request.getRequestURL().toString()) && !redirectUrl.contains("login") && !redirectUrl.contains("/user/index") && !redirectUrl.contains("reguser"))
            return redirectUrl;
        return StringUtil.empty;
    }


    public void setRedirectUrl(String redirectUrl) {
        this.redirectUrl = redirectUrl;
    }


    public BaseUserAction() {

    }

    protected OnlineManager onlineManager;

    @Ref(name = TXWebIoc.onlineManager)
    public void setOnlineManager(OnlineManager onlineManager) {
        this.onlineManager = onlineManager;
    }


    @Safety
    public void setAllowHost(String[] allowHost) {
        this.allowHost = allowHost;
    }

    @Safety
    public void setCookieDate(int cookieDate) {
        if (cookieDate > DateUtil.MINUTE)
            this.cookieDate = cookieDate;
    }

    @Safety
    public void setValidate(String validate) {
        this.validate = validate;
    }

    @Safety
    public int getMode() {
        return mode;
    }

    @Safety
    public void setMode(int mode) {
        this.mode = mode;
    }


    public void setSafeManageLogin(boolean safeManageLogin) {
        this.safeManageLogin = safeManageLogin;
    }

    private PermissionDAO permissionDAO;

    @Ref(name = TXWebIoc.permissionDAO)
    public void setPermissionDAO(PermissionDAO permissionDAO) {
        this.permissionDAO = permissionDAO;
    }

    @Operate(caption = "用户登录")
    public void login() throws Exception {

        boolean phoneLogin = false;
        long smsValidateTime = ObjectUtil.toLong(session.getAttribute(TXWeb.jspxSmsValidateTime));
        if (StringUtil.isMobile(loginId) && smsValidateTime > 0) {
            phoneLogin = true;
        }
        int loginTimes = ObjectUtil.toInt(session.getAttribute(Environment.id_loginTimes));
        loginTimes++;
        session.setAttribute(Environment.id_loginTimes, loginTimes);
        Map<String, String> loginInfo = null;
        if (mode==3||phoneLogin) {
            String sValidate = (String) session.getAttribute(TXWeb.jspxSmsValidate);
            if (System.currentTimeMillis() - smsValidateTime > DateUtil.MINUTE * 10) {
                addFieldInfo(Environment.warningInfo, language.getLang(LanguageRes.validationTimeFailure));
                return;
            }
            if (loginTimes > 5) {
                addFieldInfo(Environment.warningInfo, language.getLang(LanguageRes.validationFailureLimitTimes));
                setActionResult(ROC);
            }
            loginInfo = onlineManager.login(this, LoginField.Sms, loginId, sValidate, YesNoType.NO, cookieDate, 0);
        } else {
            String sValidate = (String) session.getAttribute(TXWeb.jspxValidate);
            if (sValidate == null) sValidate = StringUtil.empty;
            long validateTime = ObjectUtil.toLong(session.getAttribute(TXWeb.jspxValidateTime));
            if (System.currentTimeMillis() - validateTime > DateUtil.MINUTE * 10) {
                addFieldInfo(Environment.warningInfo, language.getLang(LanguageRes.validationTimeFailure));
                return;
            }
            if (loginTimes > 2)
            {
                if (!sValidate.equalsIgnoreCase(validate))
                {
                    JSONObject json = new JSONObject();
                    json.put(Environment.id_success, 0);
                    json.put(Environment.id_loginTimes, loginTimes);
                    json.put(Environment.infoType, Environment.warningInfo);
                    json.put(Environment.id_message, language.getLang(LanguageRes.validationFailure));
                    JSONArray jsonArray = new JSONArray();
                    for (String info : getFieldInfo().values()) {
                        jsonArray.put(info);
                    }
                    json.put(Environment.id_message_list, jsonArray);
                    setResult(json);
                    setActionResult(ROC);
                    return;
                }
            }
            loginInfo = onlineManager.login(this, field, loginId, password, YesNoType.NO, cookieDate, 0);
        }

        if (!loginInfo.isEmpty()) {
            getFieldInfo().putAll(loginInfo);

            JSONObject json = new JSONObject();
            json.put(Environment.id_success, 0);
            json.put(Environment.id_loginTimes, loginTimes);
            json.put(Environment.infoType, Environment.warningInfo);
            JSONArray jsonInfo = new JSONArray();
            jsonInfo.put(loginInfo.values());
            json.put(Environment.id_message, jsonInfo);
            JSONArray jsonArray = new JSONArray();
            for (String info : getFieldInfo().values()) {
                jsonArray.put(info);
            }
            json.put(Environment.id_message_list, jsonArray);
            setResult(json);
            setActionResult(ROC);

            return;
        }

        IUserSession userSession = onlineManager.getUserSession(this);
        if (isGuest()) {
            addFieldInfo(Environment.warningInfo, language.getLang(LanguageRes.loginFailure));
            return;
        }
        Map<String, String> infoMap = onlineManager.getSafePrompt(userSession.getUid());
        for (String info : infoMap.values()) {
            addActionMessage(info);
        }
        addActionMessage(language.getLang(LanguageRes.loginSuccess));
        cleanLoginSign();
        String redirectUrl = getString(KEY_RedirectUrl);
        if (!StringUtil.isNULL(redirectUrl) && !redirectUrl.endsWith(request.getRequestURI()) && !redirectUrl.endsWith(request.getRequestURL().toString()) && !redirectUrl.contains("login") && !redirectUrl.contains("/user/index") && !redirectUrl.contains("reguser")) {
            put(KEY_RedirectUrl,redirectUrl);
            setActionResult(REDIRECT);
        } else {
            JSONObject json = new JSONObject();
            json.put(Environment.id_success, 1);
            json.put(Environment.id_loginTimes, loginTimes);
            json.put(Environment.infoType, Environment.promptInfo);
            json.put(Environment.id_message, language.getLang(LanguageRes.loginSuccess));

            JSONArray jsonArray = new JSONArray();
            for (String info : getFieldInfo().values()) {
                jsonArray.put(info);
            }
            json.put(Environment.id_message_list, jsonArray);
            setResult(json);
            setActionResult(ROC);
        }

    }


    /**
     * 登录成功后删除登录标识
     */
    private void cleanLoginSign()
    {
        session.removeAttribute(Environment.id_loginTimes);
        session.removeAttribute(TXWeb.jspxSmsValidate);
        session.removeAttribute(TXWeb.jspxSmsValidateTime);
        session.removeAttribute(TXWeb.jspxValidateTime);
        session.removeAttribute(TXWeb.jspxValidate);
    }

    @Validate(formId = "loginForm")
    @Operate(caption = "管理员登录")
    public void manageLogin() throws Exception {
        int loginTimes = ObjectUtil.toInt(session.getAttribute(Environment.id_loginTimes));
        if (loginTimes > config.getInt(Environment.maxLoginTimes, 5)) {
            String sValidate = (String) session.getAttribute(TXWeb.jspxValidate);
            if (sValidate == null) sValidate = StringUtil.empty;
            if (!sValidate.equalsIgnoreCase(validate)) {
                addFieldInfo(Environment.warningInfo, language.getLang(LanguageRes.validationFailure));
                return;
            }
        }
        loginTimes++;

        Map<String, String> loginInfo = onlineManager.login(this, field, loginId, password, YesNoType.NO, cookieDate, 0);
        if (!loginInfo.isEmpty()) {
            getFieldInfo().putAll(loginInfo);
            session.setAttribute(Environment.id_loginTimes, loginTimes);
            return;
        }
        IUserSession userSession = onlineManager.getUserSession(this);
        put(Key_UserSession, userSession);
        if (safeManageLogin) {
            if (isGuest()) {
                addFieldInfo(Environment.warningInfo, language.getLang(LanguageRes.loginFailure));
                session.setAttribute(Environment.id_loginTimes, loginTimes);
                return;
            }
            userSession.getMember().setMemberRoles(permissionDAO.getMemberRoles(userSession.getUid()));
            if (EnvFactory.getEnvironmentTemplate().getBoolean(Environment.permission) && userSession.getMember().getMaxUserType() < UserType.INTENDANT) {
                addFieldInfo(Environment.warningInfo, language.getLang(LanguageRes.loginFailureNeedPower) + userSession.getMember().getMaxUserType());
                return;
            }
        }

        String redirectUrl = getString(KEY_RedirectUrl);
        if (!StringUtil.isNULL(redirectUrl) && !redirectUrl.endsWith(request.getRequestURI()) && !redirectUrl.endsWith(request.getRequestURL().toString()) && !redirectUrl.contains("login") && !redirectUrl.contains("/user/index")) {
            setActionResult(REDIRECT);
        } else {
            session.setAttribute(Environment.id_loginTimes, 0);
            setActionResult(SUCCESS);
        }
    }


    @Operate(caption = "退出", submit = false)
    public void exit() throws Exception {
        onlineManager.exit(this);
        session.setAttribute(Environment.id_loginTimes, 0);
        setActionResult(SUCCESS);
    }

    private boolean isSafeRefer(String url) {
        if (StringUtil.isNULL(url)) return true;
        if (!ArrayUtil.inArray(allowHost, request.getServerName(), true))
            allowHost = ArrayUtil.add(allowHost, request.getServerName());
        for (String host : allowHost) {
            if (url.contains(host)) return true;
        }
        return false;
    }


    @Override
    public String execute() throws Exception {
        IUserSession userSession = onlineManager.getUserSession(this);
        if (!isGuest()) {
            //登录成功
            put("userName", userSession.getName());
            session.removeAttribute(Environment.id_loginTimes);
            put(Environment.id_loginTimes, 0);
        }
        if (!TXWeb.httpPOST.equalsIgnoreCase(request.getMethod())) {
            if (isMethodInvoked()) {
                addFieldInfo(Environment.warningInfo, language.getLang(LanguageRes.illegalOperation));
                if (session != null) onlineManager.deleteUserSession(userSession.getSid(), userSession.getUid());
            }

            String url = request.getHeader(RequestUtil.requestReferer);
            if (isSafeRefer(url) && session != null) {
                session.setAttribute(KEY_RedirectUrl, url);
            }
            //非提交方式
            loginId = StringUtil.empty;
        }

        if (session != null) {
            put(Environment.id_loginTimes, ObjectUtil.toInt(session.getAttribute(Environment.id_loginTimes)));
        }
        return getActionResult();
    }
}